package com.cicoding.tcp.server;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author: zhouwenjie
 * @description: 心跳检测处理器
 * @create: 2022-03-25 16:12
 **/
@Slf4j
@Component
@ChannelHandler.Sharable
public class HeartBeatServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        // 接收到心跳请求，处理心跳消息，否则进入下一处理流程，心跳规则（ping,pong）
        String s = (String) msg;
        if ("ping".equals(s)) {
            ctx.writeAndFlush("pong");
        } else {
            //fireChannelRead 表示传递消息至下一个处理器
            ctx.fireChannelRead(msg);
        }
    }

    /**
     * 功能描述: 心跳检测
     *
     * @param ctx 这里的作用主要是解决断网，弱网的情况发生
     * @param evt
     * @return void
     * @author zhouwenjie
     * @date 2020/4/3 17:02
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        String socketString = ctx.channel().remoteAddress().toString();
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                log.info("Client RSU: " + socketString + " READER_IDLE 读超时");
                ctx.disconnect();
            }
        }
    }

    /**
     * 在处理过程中引发异常时被调用
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("[server] heart response error: {}", cause.getMessage());
        ctx.fireExceptionCaught(cause);
    }
}

